<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>es6高级2</title>
</head>

<body>
    <div id="app">
        {{message}}
        <div>
            <h1>{{message}}</h1>
        </div>
        <div v-html="htmlData"></div>
        <input v-model="modelData" value="" /> {{modelData}}
    </div>
</body>
<script>
    // 1:21:17
    class Kvue extends EventTarget {
        constructor(options) {
            super()
            this.$options = options
            this.compile()
            this.observe(this.$options.data)
        }
        observe(data) {
            let keys = Object.keys(data)
            keys.forEach(key => {
                this.defineProperty(data, key, data[key])
            })
        }
        defineProperty(data, key, value) {
            let _this = this
            Object.defineProperty(data, key, {
                enumerable: true,
                configurable: true,
                get() {
                    console.log("get...")
                    return value
                },
                set(newValue) {
                    // let event = new Event(key)
                    let event = new CustomEvent(key, {
                        detail: newValue
                    })
                    _this.dispatchEvent(event)
                    console.log("set...")
                    value = newValue;
                }
            });
        }
        compile() {
            let el = document.querySelector(this.$options.el)
            this.compileNode(el)
        }
        compileNode(el) {
            let childNodes = el.childNodes
            childNodes.forEach(node => {
                if (node.nodeType === 1) {
                    // 标签 
                    let attrs = node.attributes;
                    console.log(attrs);
                    [...attrs].forEach(attr => {
                        console.log(attr)
                        let attrName = attr.name
                        let attrValue = attr.value
                        if (attrName.indexOf('v-') === 0) {
                            attrName = attrName.substr(2)
                            if (attrName === "html") {
                                node.innerHTML = this.$options.data[attrValue]
                            } else if (attrName === "model") {
                                node.value = this.$options.data[attrValue]
                                node.addEventListener('input', e => {
                                    // console.log(e.target.value)
                                    //因为监听
                                    this.$options.data[attrValue] = e.target.value
                                })
                            }
                        }
                    });
                    if (node.childNodes.length > 0) {
                        this.compileNode(node)
                    }
                } else if (node.nodeType === 3) {
                    // 文本
                    let reg = /\{\{\s*(\S+)\s*\}\}/g
                    let textContent = node.textContent
                    if (reg.test(textContent)) {
                        console.log(RegExp.$1)
                        let $1 = RegExp.$1
                        // node.textContent = this.$options.data[$1]
                        node.textContent = node.textContent.replace(reg, this.$options.data[$1])
                        this.addEventListener($1, e => {
                            // 重新渲染
                            // console.log(this.$options.data[$1])
                            // console.log(e.detail)
                            let oldValue = this.$options.data[$1]
                            let reg = new RegExp(oldValue);
                            node.textContent = node.textContent.replace(reg, e.detail)
                        })
                    }
                }
            });
        }
    }
</script>
<script>
    let vm = new Kvue({
        el: '#app',
        data: {
            message: "测试数据",
            htmlData: "html数据",
            modelData: "绑定数据"
        }
    })
    setTimeout(() => {
        vm.$options.data.message = "修改数据"
    }, 1000)

</script>

<script>
    // 数据劫持
    let data = {
        message: "测试数据"
    }
    Object.defineProperty(data, 'message', {
        configurable: true,//默认 false
        enumerable: false, //默认 false
        get() {
            console.log("get...")
            return "测试数据"
        },
        set(newValue) {
            // console.log("set...", newValue)
        }
    })
    data.message = "修改"

    delete data.message
</script>


<script>
    // proxy
    let obj = {
        name: "张三",
        age: 20
    }
    let newObj = new Proxy(obj, {
        get(target, key) {
            console.log("proxy1")
            return target[key]
        },
        set(target, key, newValue) {
            target[key] = newValue
            console.log("proxy2")
            return true
        },
        has(target, key) {
            console.log("has")
            return true
        },


    })

    // newObj.name = "sss";

    // newObj.name = "李四"

    console.log("name" in newObj)

</script>

</html>